<template>
  <div>
    <div>
      场景一
      <button @click="numHandle">修改ref基本类型</button> {{ num }}
    </div><br>
    <div style="margin-top: 20px;">
      场景二
      <button @click="objHandle">修改ref对象类型</button> {{ obj }}
    </div><br>
    <div style="margin-top: 20px;">
      场景三 reactive 创建对象
      <button @click="handleCity">修改reactive对象属性</button> {{ reactiveObj }}
      <button @click="handleReactiveObj">修改reactive对象</button>
    </div><br>
    <div style="margin-top: 20px;">
      场景四 reactive 创建对象
      <button @click="changeName">修改reactive对象name</button> {{ reactivePerson }}
      <button @click="handlePerson">修改reactive对象</button>
      <button @click="changeAge">修改reactive对象age</button><br><br>
      <div style="padding: 10px;">
        <button @click="changeChildrenAge">修改reactive changeChildrenAge对象age</button><br>
        <button @click="changeChildren">修改reactive changeChildrenAge对象</button><br>
      </div>
    </div><br>
  </div>
</template>

<script setup>
import { reactive, ref, watch } from 'vue';

/**
 * watch的使用场景
 * watch 的第一个参数可以是不同形式的“数据源”：它可以是一个 ref (包括计算属性)、一个响应式对象、一个 getter 函数、或多个数据源组成的数组：
*/

//场景一 ref监听基本类型数据
const num = ref(1)
const numHandle = () => {
  num.value++;
}
const stopWatch = watch(num, (newValue, oldValue) => {
  console.log(newValue, oldValue);
  if (num.value === 10) {
    stopWatch();//停止监听
  }
})

//场景二 使用ref监听对象
const obj = ref({ name: "zhang san", age: 12, obj: {x: 12.3, y: 0.56} })
const objHandle = () => {
  // obj.value.age++
  // obj.value.obj.x = 25.3
  obj.value = {name: 'kkkksdj'}
}

console.log(obj, 'kkkkkkk');

//这里可以不写deep深度监听，把obj改成obj.value
const stopWatch2 = watch(obj.value, (n, o) => {
  console.log(n, o);
}) //{ deep: true }

//场景三 使用reactive创建对象，默认是隐式深度监听，无法通过deep:false关闭的
const reactiveObj = reactive({
  name: "wang da",
  age: 24,
  city: "Guang Zhou",
  location: {
    x: 23.6,
    y: 45.8
  }
})

console.log(reactiveObj, "reactiveObj");

const handleCity = () => {
  // reactiveObj.name = "Li Si"
  reactiveObj.location.x = 56.32
}
const handleReactiveObj = () => {
  Object.assign(reactiveObj, { name: "zhang san", age: 35, city: "Cheng du" })

}

const stopWatch55 = watch(reactiveObj, (n, o) => {
  console.log(n, o);
  if (reactiveObj.age === 30) {
    stopWatch55()
  }
})

//场景四：监听对象里面的某个key的变化，通过创建一个getter方法 可以使用箭头函数返回监听的属性值
const reactivePerson = reactive({
  name: 'xiao lizi',
  age: 29,
  children: {
    name: "xiaoxiao li",
    age: 8
  }
})

const changeName = () => {
  reactivePerson.name = reactivePerson.name + "~"
}
const changeAge = () => {
  reactivePerson.age++
}
const handlePerson = () => {
  Object.assign(reactivePerson, { age: 21 })
}
//1、监听的是name，name值是一个基本类型  修改age 不会发生改变，写成函数形式就可以监听了
watch(() => reactivePerson.name, (n, o) => {
  console.log(n, o);
})
//2、监听的属性值是个对象，可以直接写属性值，但是
// watch(reactivePerson.children, (n,o) => {
//   console.log(n, o);

// })
const changeChildrenAge = () => {
  reactivePerson.children.age++;
}
const changeChildren = () => {
  reactivePerson.children = {
    name: "kk-kekd",
    age: 20
  }
}

// 补充： deep: true 监听是 对象的指针地址是否改变，然后深度监听后，就可以监听到对象里面的属性值改变。
</script>

<style scoped lang='scss'></style>
